
interface IRequestOptions {
    method?: 'GET' | 'POST' | 'PUT' | 'DELETE';
    headers?: Record<string, string>;
    body?: any;
    timeout?: number;
}

class HttpRequest {
    private baseURL: string;
    private interceptors: {
        request: Array<(config: IRequestOptions) => IRequestOptions>;
        response: Array<(response: Response) => Response>;
    };

    constructor(baseURL: string = '') {
        this.baseURL = baseURL;
        this.interceptors = {
            request: [],
            response: []
        };
    }

    async request<T>(url: string, options: IRequestOptions = {}): Promise<T> {
        const controller = new AbortController();
        const timeout = options.timeout || 10000;
        const timer = setTimeout(() => controller.abort(), timeout);

        try {
            // 处理请求拦截
            let configTmp = {
                method: options.method || 'GET',
                headers: { 'Content-Type': 'application/json' },
                ...options,
                signal: controller.signal
            };

            let config = await this.applyRequestInterceptors(configTmp);

            if (config.body && typeof config.body !== 'string') {
                config.body = JSON.stringify(config.body);
            }

            const fullUrl = this.baseURL + url;
            let response = await fetch(fullUrl, config);

            // 处理响应拦截
            this.interceptors.response.forEach(interceptor => {
                response = interceptor(response);
            });

            if (!response.ok) {
                throw new Error(`HTTP ${response.status}: ${response.statusText}`);
            }

            return await response.json();
        } catch (error) {
            throw this.normalizeError(error);
        } finally {
            clearTimeout(timer);
        }
    }

    private normalizeError(error: unknown): Error {
        if (error instanceof Error) {
            if (error.name === 'AbortError') {
                return new Error('请求超时，请检查网络连接');
            }
            return error;
        }
        return new Error('未知网络错误');
    }


    private async applyRequestInterceptors(config: IRequestOptions): Promise<IRequestOptions> {
        let currentConfig = { ...config }; // 创建副本

        for (const interceptor of this.interceptors.request) {
            try {
                currentConfig = await (typeof interceptor === 'function'
                    ? interceptor(currentConfig)
                    : currentConfig);

                if (!currentConfig || typeof currentConfig !== 'object') {
                    throw new Error('拦截器必须返回配置对象');
                }
            } catch (error) {
                console.error('请求拦截器执行失败:', error);
                throw error;
            }
        }

        return currentConfig;
    }


    // 快捷方法
    get<T>(url: string, params?: Record<string, any>, options?: Omit<IRequestOptions, 'method' | 'body'>) {
        const query = params ? `?${new URLSearchParams(params)}` : '';
        return this.request<T>(url + query, { ...options, method: 'GET' });
    }

    post<T>(url: string, body: any, options?: Omit<IRequestOptions, 'method'>) {
        return this.request<T>(url, { ...options, method: 'POST', body });
    }

    // 拦截器方法
    useRequestInterceptor(interceptor: (config: IRequestOptions) => IRequestOptions) {
        this.interceptors.request.push(interceptor);
    }

    useResponseInterceptor(interceptor: (response: Response) => Response) {
        this.interceptors.response.push(interceptor);
    }
}

// // 使用示例
// const api = new HttpRequest('https://api.example.com');
// api.useRequestInterceptor(config => {
//     config.headers = { ...config.headers, Authorization: 'Bearer token' };
//     return config;
// });

// // 获取数据
// api.get<{ id: number }>('/user/123').then(data => {
//     console.log(data.id);
// });
